package com.filepublic.demo.server.service.impl;

import com.filepublic.demo.common.constant.EmailTextConstant;
import com.filepublic.demo.common.constant.ExceptionConstant;
import com.filepublic.demo.common.constant.RedisKeyConstant;
import com.filepublic.demo.common.constant.RedisTimeConstant;
import com.filepublic.demo.common.exception.BaseLogicException;
import com.filepublic.demo.common.util.EmailUtil;
import com.filepublic.demo.common.util.MyStringUtil;
import com.filepublic.demo.pojo.dto.UserEnrollDto;
import com.filepublic.demo.pojo.dto.UserLoginDto;
import com.filepublic.demo.pojo.entity.UserEntity;
import com.filepublic.demo.pojo.query.UserBaseQuery;
import com.filepublic.demo.pojo.vo.UserVo;
import com.filepublic.demo.server.mapper.UserBaseMapper;
import com.filepublic.demo.server.service.AsyncService;
import com.filepublic.demo.server.service.UserService;
import lombok.extern.slf4j.Slf4j;
import org.apache.catalina.User;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.data.redis.core.ValueOperations;
import org.springframework.mail.SimpleMailMessage;
import org.springframework.mail.javamail.JavaMailSender;
import org.springframework.scheduling.annotation.Async;
import org.springframework.stereotype.Service;

import javax.annotation.Resource;
import javax.servlet.http.HttpServletRequest;
import java.time.LocalDate;
import java.util.UUID;
import java.util.concurrent.TimeUnit;

import static com.fasterxml.jackson.databind.util.ClassUtil.name;

@Service
@Slf4j
public class UserServiceImpl implements UserService {

    @Resource
    UserBaseMapper userBaseMapper;

    @Resource
    RedisTemplate redisTemplate;

    @Resource
    AsyncService asyncService;

    /**
     * 用户登录
     * @param userLoginDto
     */
    @Override
    public UserVo login(UserLoginDto userLoginDto) {
        UserBaseQuery userBaseQuery = new UserBaseQuery();

        //将userLoginDto转入query
        BeanUtils.copyProperties(userLoginDto,userBaseQuery);

        //获取用户对象
        UserEntity userEntity = userBaseMapper.selectUser(userBaseQuery);

        if(userEntity == null){
            log.error("用户账号密码错误");
            //抛出异常
            throw new BaseLogicException(ExceptionConstant.USER_NAME_PASS_ERROR);
        }

        UserVo userVo = UserVo.builder()
                .userId(userEntity.getUserId())
                .date(userEntity.getStartDate())
                .name(userEntity.getName())
                //生成一个唯一token
                .token(UUID.randomUUID().toString())
                .build();

        //将用户信息存入redis，token为key
        addTokenInRedis(userVo);

        return userVo;
    }

    //将信息存入redis
    public void addTokenInRedis(UserVo userVo){
        ValueOperations valueOperations = redisTemplate.opsForValue();

        valueOperations.set(RedisKeyConstant.TOKEN_KEY+userVo.getToken(),userVo.getUserId(),RedisTimeConstant.TOKEN_TIME,TimeUnit.MILLISECONDS);
    }

    /**
     * 用户注册
     * @param userEnrollDto
     */
    @Override
    public void enroll(UserEnrollDto userEnrollDto) {
        //校验验证码
        String captcha = (String)redisTemplate.opsForValue().get(RedisKeyConstant.CAPTCHA_KEY + userEnrollDto.getUserName());
        if(captcha == null){
            //抛出验证码过期异常
            throw new BaseLogicException(ExceptionConstant.CAPTCHA_OUT_TIME);
        }
        if(!userEnrollDto.getCaptcha().equals(captcha)){
            //抛出验证码错误异常
            throw new BaseLogicException(ExceptionConstant.CAPTCHA_ERROR);
        }

        //生成用户新的邮箱号
        String userId = MyStringUtil.userNameToUserId(userEnrollDto.getUserName());

        UserEntity userEntity = UserEntity.builder()
                .userId(userId)
                .name(userId)
                .password(userEnrollDto.getPassword())
                .userName(userEnrollDto.getUserName())
                .startDate(LocalDate.now())
                .build();

        //增加用户数据
        userBaseMapper.insertUser(userEntity);
    }

    /**
     * 用户注销
     * @param httpServletRequest
     */
    @Override
    public void logout(HttpServletRequest httpServletRequest) {
        String token = httpServletRequest.getHeader("token");
        redisTemplate.delete(RedisKeyConstant.TOKEN_KEY + token);
    }

    /**
     * 验证码
     * @param emailUser
     * @return
     */
    @Override
    public void captcha(String emailUser){
        //查询redis，是否已经发送过验证码
        String captchaKey = RedisKeyConstant.CAPTCHA_KEY +emailUser;
        if(redisTemplate.opsForValue().get(captchaKey) != null){
            log.error("{}重复发送验证码",emailUser);
            //抛出异常(提示不能重复发送验证码)
            throw new BaseLogicException(ExceptionConstant.RE_POST_CAPTCHA);
        }

        //查询有无该账号
        UserBaseQuery userBaseQuery = new UserBaseQuery();
        userBaseQuery.setUserName(emailUser);
        UserEntity userEntity = userBaseMapper.selectUser(userBaseQuery);

        if(userEntity != null){
            log.error("已有账号:{}",emailUser);
            //抛异常，已经有该账号
            throw new BaseLogicException(ExceptionConstant.RE_ENROLL_ERROR);
        }
        //发送验证码
        asyncService.sendEmail(emailUser);
    }

}











